package com.chenyaowei.cart.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.chenyaowei.cart.bo.CartItemBO;
import com.chenyaowei.cart.service.ICartService;
import com.chenyaowei.cart.vo.CartVO;
import com.chenyaowei.common.constant.CacheConstants;
import com.chenyaowei.common.core.redis.RedisCache;
import com.chenyaowei.common.utils.SecurityUtils;
import com.chenyaowei.product.domain.CywProSkuInfo;
import com.chenyaowei.product.domain.CywProSkuSaleAttrValue;
import com.chenyaowei.product.service.ICywProSkuInfoService;
import com.chenyaowei.product.service.ICywProSkuSaleAttrValueService;
import com.github.pagehelper.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements ICartService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICywProSkuInfoService skuInfoService;

    @Autowired
    private ICywProSkuSaleAttrValueService saleAttrValueService;



    /**
     * 修改购物项数量
     *
     * @param skuId
     * @param num
     */
    @Override
    public void changeCountItem(Long skuId, Integer num) {
        Long userId = SecurityUtils.getUserId();
        BoundHashOperations<String, Object, Object> operations = redisCache.getBoundHashOps(CacheConstants.CART_PREFIX + userId);
        CartItemBO cartItem = JSON.parseObject((String) operations.get(skuId.toString()), CartItemBO.class);
        cartItem.setCount(num);
        operations.put(skuId.toString(), JSON.toJSONString(cartItem));
    }

    @Override
    public List<CartItemBO> getUserCartItems() {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return null;
        }
        String cartKey = CacheConstants.CART_PREFIX + userId;
        List<CartItemBO> cartItems = getCartItems(cartKey);
        // 获取所有被选中的购物项
        List<CartItemBO> list = cartItems.stream().filter(cartItem -> cartItem.getChecked()).collect(Collectors.toList());
        // 更新为最新价格
        List<Long> skuIds = cartItems.stream().filter(cartItem -> cartItem.getChecked()).map(CartItemBO::getSkuId).collect(Collectors.toList());
        Map<Long, BigDecimal> latestPriceMap = skuInfoService.selectListBySkuIds(skuIds).stream().collect(Collectors.toMap(CywProSkuInfo::getSkuId, CywProSkuInfo::getPrice));
        list.forEach(item -> item.setPrice(latestPriceMap.get(item.getSkuId())));
        return list;
    }

    /**
     * 选中商品项
     *
     * @return
     */
    @Override
    public void checkedItem(Long skuId, Integer checked) {
        Long userId = SecurityUtils.getUserId();
        BoundHashOperations<String, Object, Object> operations = redisCache.getBoundHashOps(CacheConstants.CART_PREFIX + userId);
        CartItemBO cartItem = JSON.parseObject((String) operations.get(skuId.toString()), CartItemBO.class);
        cartItem.setChecked(checked == 1 ? true : false);
        operations.put(skuId.toString(), JSON.toJSONString(cartItem));
    }

    /**
     * 移除商品项
     *
     * @return
     */
    @Override
    public Long deleteItem(Long skuId) {
        Long userId = SecurityUtils.getUserId();
        BoundHashOperations<String, Object, Object> operations = redisCache.getBoundHashOps(CacheConstants.CART_PREFIX + userId);
        return operations.delete(skuId.toString());
    }

    /**
     * 添加商品到购物车
     *
     * @return
     */
    @Override
    public Boolean addItem(Long skuId, Integer num) {
        Long userId = SecurityUtils.getUserId();
        BoundHashOperations<String, Object, Object> operations = redisCache.getBoundHashOps(CacheConstants.CART_PREFIX + userId);
        String cacheCartItem = (String) operations.get(skuId.toString());
        if (StringUtil.isNotEmpty(cacheCartItem)) {
            //购物车已经存在该商品
            CartItemBO cartItemBO = JSON.parseObject(cacheCartItem, CartItemBO.class);
            cartItemBO.setCount(cartItemBO.getCount() + num);
            operations.put(skuId.toString(), JSON.toJSONString(cartItemBO));
        } else {
            CywProSkuInfo skuInfo = skuInfoService.selectCywProSkuInfoBySkuId(skuId);
            List<CywProSkuSaleAttrValue> skuSaleAttrValues = saleAttrValueService.selectListBySkuIds(Arrays.asList(skuId));
            //购物车不存在该商品
            CartItemBO cartItemBO = new CartItemBO();
            cartItemBO.setSpuId(skuInfo.getSpuId());
            cartItemBO.setCatelogId(skuInfo.getCatalogId());
            cartItemBO.setSkuId(skuInfo.getSkuId());
            cartItemBO.setChecked(true);
            cartItemBO.setTitle(skuInfo.getSkuTitle());
            cartItemBO.setSkuPic(skuInfo.getSkuDefaultImg());
            cartItemBO.setPrice(skuInfo.getPrice());
            cartItemBO.setCount(num);

            List<CartItemBO.SaleAttrValue> saleAttrValues = new ArrayList<>();
            skuSaleAttrValues.forEach(item -> {
                CartItemBO.SaleAttrValue saleAttrValue = new CartItemBO.SaleAttrValue();
                BeanUtils.copyProperties(item, saleAttrValue);
                saleAttrValues.add(saleAttrValue);
            });
            cartItemBO.setSkuAttrsVals(saleAttrValues);

            operations.put(skuId.toString(), JSON.toJSONString(cartItemBO));
        }
        return operations.hasKey(skuId.toString());
    }

    /**
     * 获取整个购物车
     *
     * @return
     */
    @Override
    public CartVO getCart() {
        Long userId = SecurityUtils.getUserId();
        CartVO cartVO = new CartVO();
        List<CartItemBO> cartItems = getCartItems(CacheConstants.CART_PREFIX + userId);
        cartVO.setItems(cartItems);
        return cartVO;
    }

    /**
     * 获取购物车所有商品
     *
     * @param cartKey
     * @return
     */
    private List<CartItemBO> getCartItems(String cartKey) {
        BoundHashOperations<String, Object, Object> operations = redisCache.getBoundHashOps(cartKey);
        List<Object> cartItems = operations.values();
        return CollectionUtil.isNotEmpty(cartItems) ? cartItems.stream().map(value -> JSON.parseObject(value.toString(), CartItemBO.class)).collect(Collectors.toList()) : null;
    }
}
